package com.hrt.serial.modbus;

import com.btcode.common.BitType;
import com.btcode.common.ByteUnit;
import com.btcode.common.PropertiesUnit;
import com.btcode.db.result.Row;
import com.hrt.datasender.datacollect.drive.DriveConfigModel;
import com.hrt.db.DBManager;
import com.hrt.util.ModbusDecodeUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * PLC-modbusTcp数据解析类
 * 
 * @author wencheng
 */
public class ModbusDataDecodePlcTcp extends ModbusDataDecode {
    /**
     * 报文前缀长度，6位MBAP,1位从站编号，1位功能码，1位数据长度
     */
    private final int msgPrefixLength = 9;
    private int plcDeviation = 0;


    public ModbusDataDecodePlcTcp() {
        String strPlcDeviation = PropertiesUnit.getValue("plcDeviation");
        if(strPlcDeviation!=null&&!"".equals(strPlcDeviation)){
            plcDeviation = Integer.parseInt(strPlcDeviation);
        }
    }

    /**
     * 
     * @param data
     * @param byteLength
     * @return
     */
    public synchronized List<ModbusDataModel> dataModelDecode(byte[] data, int byteLength, DriveConfigModel deviceConfigs) {
        HashMap<String, String> configsMap = deviceConfigs.getConfig();
        int startNo = Integer.parseInt(configsMap.get("startNo"));
        List<Row> plcPointRows = deviceConfigs.getPlcPointRows();

        List<ModbusDataModel> models = null;
        byte[] finalByteData = mergeData(data, byteLength);

        ModbusDataFrameDecoderBase modbusMsgModel = new ModbusDataFrameDecoderTCP(finalByteData);

        do {
            try {
                finalByteData = modbusMsgModel.next();
            }
            catch (MsgLengthException e) {
                byte[] leftMsg = modbusMsgModel.getLeftMsg();
                setTempByteData(leftMsg, leftMsg.length);
                break;
            }
            catch (CRCException e) {
                break;
            }

            models = new ArrayList<>();

            for(Row row:plcPointRows){
                String id = row.getSafeString("ID");
                String paramCodeBus = row.getSafeString("PARAM_CODE_BUS");
                String pointDataType = row.getSafeString("POINT_DATA_TYPE");
                String pointPosition = row.getSafeString("POINT_POSITION");
                String[] arrPointPos = pointPosition.split("\\.");
                int iPointPosition = Integer.parseInt(arrPointPos[0]);
                int iBitPos = Integer.parseInt(arrPointPos[1]);
                String isMeasValue = row.getSafeString("IS_MEAS_VALUE");
                boolean bIsMeasValue = false;
                if("0".equals(isMeasValue)){
                    bIsMeasValue = true;
                }
                BitType bitType;
                switch (pointDataType){
                    case "float":
                        bitType = BitType.bit32;
                        break;
                    case "int":
                        bitType = BitType.bit16;
                        break;
                    case "bit":
                        bitType = BitType.bit16;
                        break;
                    case "date":
                        bitType = BitType.bit16;
                        break;
                        default:
                            bitType = BitType.bit32;
                            break;
                }

                byte[] dataItem = new byte[bitType.byteLength];
                System.arraycopy(finalByteData,msgPrefixLength + (iPointPosition - startNo) * 2,
                    dataItem, 0, bitType.byteLength);
                Object value = ByteUnit.ConvertByteToDoubleX(dataItem, bitType);

                /**
                 * bit类型数据获取
                 */
                if("bit".equals(pointDataType)) {
                    Double dValue = (Double) value;
                    int iTest = dValue.intValue();
                    String bin = Integer.toBinaryString(iTest);
                    int[] arrBin = new int[16];
                    for (int i = 0; i < 16; i++) {
                        if(i<bin.length()){
                            arrBin[i] = Integer.parseInt(bin.substring(i,i+1));
                        }
                        else{
                            arrBin[i] = 0;
                        }
                    }
                    value = arrBin[iBitPos];
                }

                /**
                 * date类型在PLC上为连续5位int
                 */
                if("date".equals(pointDataType)){
                    String[] arrDate = new String[5];
                    for (int i = 0; i < 5; i++) {
                        dataItem = new byte[bitType.byteLength];
                        int srcPos = msgPrefixLength + (iPointPosition - startNo) * 2 + i * bitType.byteLength;
                        System.arraycopy(finalByteData, srcPos, dataItem, 0, bitType.byteLength);
                        Double dValue = ByteUnit.ConvertByteToDoubleX(dataItem, bitType);
                        arrDate[i] = dValue.toString().replace(".0","");
                    }
                    value = arrDate[0] + "年" + arrDate[1] + "月" +arrDate[2] + "日" + " " +
                        arrDate[3] + "时" + arrDate[4] + "分";
                }

                ModbusDataModel model = new ModbusDataModel();
                model.setId(paramCodeBus);
                model.setPlcIsMeasValue(bIsMeasValue);
                model.setSingleData(value);
                model.setPlcPointId(id);
                models.add(model);
            }

        } while (true);

        return models;

    }

    @Override
    public ModbusDataFrameDecoderBase getDataFrameDecoder(byte[] finalByteData) {
        ModbusDataFrameDecoderBase modbusMsgModel = new ModbusDataFrameDecoderTCP(finalByteData);
        return modbusMsgModel;
    }


}
